package cc.co.cutenimy.nimyexplore.rcp.wizards;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import cc.co.cutenimy.nimyexplore.model.connection.ConnectionOptions;
import cc.co.cutenimy.nimyexplore.model.connection.Option;
import cc.co.cutenimy.nimyexplore.model.jdbc.ConnectionInstance;
import cc.co.cutenimy.nimyexplore.model.jdbc.OptionValue;
import cc.co.cutenimy.nimyexplore.rcp.ApplicationContext;
import cc.co.cutenimy.nimyexplore.ui.grid.GridWidget;
import cc.co.cutenimy.nimyexplore.ui.provider.ImageTextLabelProvier;

public class NewConnectionWizardPage extends WizardPage {

	private static final String OPTIONS_TYPE = "OPTIONS_TYPE";
	private static final String OPTION_NAME = "optionName";
	private Group detailSectionGroup;
	private StackLayout stackLayout;
	private final Map<String, Composite> compositeMap = new HashMap<String, Composite>(
			16);
	private Text aliasText;;

	protected NewConnectionWizardPage(String pageName) {
		super(pageName);
		setTitle(NewConnectionWizard.NEWCONNECTIONWIZARD_DETAILS_PAGE_TITLE);
		setMessage("Create a new connection", IMessageProvider.INFORMATION);
	}

	public void createControl(Composite parent) {
		GridWidget.forIt(parent).num(1).apply();

		final Composite composite = new Composite(parent, SWT.NONE);
		GridWidget.forIt(composite).num(2).apply();
		GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
		Label label = new Label(composite, SWT.NONE);
		label.setText("Type");

		ComboViewer optionTypeComboViewer = new ComboViewer(composite,
				SWT.READ_ONLY);
		GridDataFactory.fillDefaults().grab(true, false)
				.applyTo(optionTypeComboViewer.getControl());
		optionTypeComboViewer.setLabelProvider(new ImageTextLabelProvier() {

			public String getText(Object element) {
				if (element instanceof ConnectionOptions) {
					return ((ConnectionOptions) element).getName();
				}
				return null;
			}
		});
		optionTypeComboViewer.add(getSupportOptions().toArray(new Object[0]));
		optionTypeComboViewer
				.addSelectionChangedListener(new ISelectionChangedListener() {

					public void selectionChanged(SelectionChangedEvent event) {
						ConnectionOptions options = (ConnectionOptions) ((IStructuredSelection) event
								.getSelection()).getFirstElement();
						createControlsForOptions(detailSectionGroup, options);
					}
				});
		Label aliasLabel = new Label(composite, SWT.NONE);
		aliasLabel.setText("Alias");

		aliasText = new Text(composite, SWT.BORDER);
		GridDataFactory.fillDefaults().grab(true, false).applyTo(aliasText);

		detailSectionGroup = new Group(composite, SWT.SHADOW_NONE);
		detailSectionGroup.setText("Details");
		GridDataFactory.fillDefaults().span(2, 1).grab(true, true)
				.minSize(SWT.DEFAULT, 400).applyTo(detailSectionGroup);
		stackLayout = new StackLayout();
		detailSectionGroup.setLayout(stackLayout);
		// createControlsForOptions(group, getSupportOptions().get(0));
		setControl(composite);
	}

	private void createControlsForOptions(final Composite parent,
			final ConnectionOptions connectionOptions) {
		Assert.isNotNull(connectionOptions);
		stackLayout.topControl = getOrCreateControlsFor(parent,
				connectionOptions);
		detailSectionGroup.layout(true);

	}

	private Control getOrCreateControlsFor(final Composite parent,
			final ConnectionOptions connectionOptions) {
		Composite composite = compositeMap.get(connectionOptions.getName());
		if (composite != null) {
			return composite;
		} else {
			Composite currentOptionComposite = new Composite(parent, SWT.NONE);
			GridWidget.forIt(currentOptionComposite).num(2).apply();
			for (final Option option : connectionOptions.getOption()) {
				Label label = new Label(currentOptionComposite, SWT.NONE);
				label.setText(option.getLabel());
				Text text = new Text(currentOptionComposite, SWT.BORDER);
				if (option.getRequired()) {
					// TODO validate and not allow empty value
				}
				GridDataFactory.fillDefaults().grab(true, false).applyTo(text);
				text.setData(OPTION_NAME, option.getName());
			}

			compositeMap.put(connectionOptions.getName(),
					currentOptionComposite);
			currentOptionComposite.setData(OPTIONS_TYPE, connectionOptions);
			return currentOptionComposite;
		}
	}

	public ConnectionInstance assemble() {
		Composite topControl = (Composite) stackLayout.topControl;
		ConnectionOptions connectionOptions = (ConnectionOptions) topControl
				.getData(OPTIONS_TYPE);
		ConnectionInstance instanceByOptions = ApplicationContext.get().from(
				connectionOptions);
		Control[] children = topControl.getChildren();
		for (Control control : children) {
			Object data = control.getData(OPTION_NAME);
			if (control instanceof Text && data != null) {
				String value = ((Text) control).getText().trim();
				instanceByOptions.setOptionValueByName((String) data,
						OptionValue.stringValue(value));
			}
		}
		return instanceByOptions;
	}

	private List<ConnectionOptions> getSupportOptions() {
		return ApplicationContext.get().loadConnectionOptions();
	}

}
